/*
 * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Intel Corporation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <stdarg.h>
#include <stdio.h> /* vsnprintf */
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <time.h>
#include <stdint.h>

// #include <stdint.h>
// #include <openssl/aes.h>

#include "sgx_trts.h"
#include "sgx_tcrypto.h"
#include <cstring>

#define AES_CMAC_BLOCK_SIZE 16
#define CMAC_KEY_SIZE 16
#define MESSAGE_SIZE 16

#define MAX_RECORD_LENGTH 300
#define MAX_ROW_NUM 10000

using namespace std;

/* 
 * printf: 
 *   Invokes OCALL to display the enclave buffer to the terminal.
 */
int printf(const char* fmt, ...)
{
    char buf[BUFSIZ] = { '\0' };
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, BUFSIZ, fmt, ap);
    va_end(ap);
    ocall_print_string(buf);
    return (int)strnlen(buf, BUFSIZ - 1) + 1;
}

void enclave_increment_array(int array[5], int len){
    for(int i=0; i<len; i++){
        printf("%d\n", array[i]);
    }
    for(int i=0; i<len; i++){
        array[i] = array[i]*2;
    }
    for(int i=0; i<len; i++){
        printf("%d\n", array[i]);
    }
}

void ecall_sum(int array[1000000], int len){
    printf("flag");
    int sum = 0;
    for(int i=0; i<len; i++){
        sum += array[i];
    }
    printf("%d\n", sum);
}

void ecall_calculate(){

    vector<int> a{1,2,3,4,5};
    sort(a.begin(), a.end(), greater<int>());
    vector<int>::iterator it;
    for(it = a.begin(); it != a.end(); it++){
        printf("%d\n", *it);
    }

}

int cal_prime(){
    int i,j,k=0;
    for(i=2; i<10000; i++){
        for(j=2; j*j<=i; j++){
            if(i%j == 0)
                break;
        }
        if(j*j > i){
            k++;
        }
    }
    return k;
}

sgx_cmac_128bit_tag_t result = {0};
sgx_cmac_128bit_tag_t readSet = {0};
sgx_cmac_128bit_tag_t writeSet = {0};
sgx_cmac_128bit_tag_t writeSet_v = {0};
uint8_t key[16] = {0};

void sgx_error_handler(sgx_status_t ret) 
{
    if (ret != SGX_SUCCESS) {
        printf("SGX error\n");
    }
}

void ecall_write_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
    }

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void ecall_read_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void ecall_delete_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        readSet[i] ^= cmac_result[i];
    }
}

void ecall_read_verify(const char* str, size_t str_len)
{
    printf("data:%s",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet_v[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
}

void ecall_verify(int* result)
{
    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");


    *result = (memcmp(readSet, writeSet, sizeof(sgx_cmac_128bit_tag_t)) == 0) ? 1:0;

    if (sizeof(writeSet) == sizeof(writeSet_v)) {
        for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
            writeSet[i] ^= writeSet_v[i];
        }
    } else {
        printf("error!\n");
        // 处理错误，可能需要打印错误信息或者采取其他适当的措施
    }
    memset(writeSet_v, 0, sizeof(sgx_cmac_128bit_tag_t));
}

void read_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void write_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
    }

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}


void read_verify(const char* str, size_t str_len)
{
    printf("data:%s",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet_v[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
}

void verify(int* result)
{
    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");


    *result = (memcmp(readSet, writeSet, sizeof(sgx_cmac_128bit_tag_t)) == 0) ? 1:0;

    if (sizeof(writeSet) == sizeof(writeSet_v)) {
        for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
            writeSet[i] ^= writeSet_v[i];
        }
    } else {
        printf("error!\n");
        // 处理错误，可能需要打印错误信息或者采取其他适当的措施
    }
    memset(writeSet_v, 0, sizeof(sgx_cmac_128bit_tag_t));
}

// char first_result[MAX_ROW_NUM][MAX_RECORD_LENGTH] = {0};
// char second_result[MAX_ROW_NUM][MAX_RECORD_LENGTH] = {0};
// char final_result[MAX_ROW_NUM][MAX_RECORD_LENGTH] = {0};
// char **first_result;
// char **second_result;
// char **final_result;
// int first_cnt=0;
// int second_cnt=0;
// int final_cnt=0;

// 获取时间戳计数器（TSC）的值
uint64_t get_tsc_value() {
    uint32_t eax, edx;
    __asm__ __volatile__("rdtsc" : "=a"(eax), "=d"(edx));
    return ((uint64_t)edx << 32) | eax;
}


int parse_record(char* record, char (*row)[MAX_FIELD_LENGTH]) 
{
    char* token;
    char* tempString = strndup(record, MAX_RECORD_LENGTH);
    int num = 0;

    token = strtok(tempString, "|");
    while (token != NULL && num < MAX_FIELD_LENGTH) {
        strlcpy(row[num], token, MAX_FIELD_LENGTH);
        num++;
        token = strtok(NULL, "|");
    }

    free(tempString);
    return num;
}

int execute_join(const char* outer_query, const char* inner_query, const char* join_col1, const char* join_col2, 
                    int outputNum, char (*output)[MAX_FIELD_LENGTH], char **result)
{
    int outer_cnt=0, inner_cnt=0;
    char outer_fields_record[MAX_RECORD_LENGTH];
    char inner_fields_record[MAX_RECORD_LENGTH];
    // 在此处调用Enclave外部的函数，将SQL语句传递给Enclave外部执行
    ocall_outer_loop(outer_query, &outer_cnt, outer_fields_record, MAX_RECORD_LENGTH);
    ocall_inner_loop(inner_query, &inner_cnt, inner_fields_record, MAX_RECORD_LENGTH);

    char outer_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    char inner_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  

    int outer_field_cnt = parse_record(outer_fields_record, outer_fields);
    int inner_field_cnt = parse_record(inner_fields_record, inner_fields);

    // for(int i=0; i<outputNum; i++) {
    //     printf("%s\n", output[i]);
    // }

    int* output_field = (int *)malloc(outputNum * sizeof(int));
    int field_cnt = 0;

    for(int i=0; i<outputNum; i++) {
        for(int j=0; j<outer_field_cnt; j++) {
            if(!strcmp(output[i], outer_fields[j])){
                strncat(result[0], outer_fields[j], MAX_FIELD_LENGTH);
                strncat(result[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = j;
                field_cnt ++;
            }
        }
        for(int j=0; j<inner_field_cnt; j++) {
            if(!strcmp(output[i], inner_fields[j])){
                strncat(result[0], inner_fields[j], MAX_FIELD_LENGTH);
                strncat(result[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = outer_field_cnt+j;
                field_cnt ++;
            }
        }
    }

    for(int i=0; i<outputNum; i++) {
        printf("%d, %s\n", output_field[i], output[i]);
    }

    int outer_id=0, inner_id=0;
    for(int i=0; i<outer_field_cnt; i++) {
        // printf("%s\n", outer_fields[i]);
        // printf("flag:%d\n", strcmp(join_col1, outer_fields[i]));
        printf("outer fields:\n");
        printf("%s, %s\n", join_col2, outer_fields[i]);
        printf("%d\n", strcmp(join_col2, outer_fields[i]));
        if(!strcmp(join_col2, outer_fields[i])) {
            outer_id = i;
        }
    }
    for(int i=0; i<inner_field_cnt; i++) {
        // printf("%s\n", inner_fields[i]);
        printf("inner fields:\n");
        printf("%s, %s\n", join_col1, inner_fields[i]);
        printf("%d\n", strcmp(join_col1, inner_fields[i]));
        if(!strcmp(join_col1, inner_fields[i])) {
            inner_id = i;
        }
    }
    // printf("field_cnt:%d\n", field_cnt);

    // printf("outerID %d\n", outer_id);
    // printf("innerID %d\n", inner_id);
    // printf("%s\n", join_col1);
    // printf("%s\n", join_col2);
    
    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH]; 

    int result_cnt = 1;

    const char delimiter[] = "|";
    printf("inner count:%d\n", inner_cnt);
    printf("outer count:%d\n", outer_cnt);
    for(int i=0; i<outer_cnt; i++){
        // uint64_t clock1 = get_tsc_value();
        enclave_get_outer_record(i, outer_record, MAX_RECORD_LENGTH);
        // uint64_t clock2 = get_tsc_value();
        // double time1 = ((double)(clock2-clock1))/(2.30e6);
        // printf("time1: %f\n", time1);

        // 创建一个足够大的数组来存储分割后的子字符串
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int outer_index = 0;
        outer_index = parse_record(outer_record, outer_row);

        for(int j=0; j<inner_cnt; j++){
            enclave_get_inner_record(j, inner_record, MAX_RECORD_LENGTH);

            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            if(strncmp(outer_row[outer_id],inner_row[inner_id],MAX_FIELD_LENGTH) == 0){
                for(int k=0; k<outputNum; k++) {
                    if(output_field[k]<outer_field_cnt) {
                        strncat(result[result_cnt], outer_row[output_field[k]], MAX_FIELD_LENGTH);
                        strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                    } else {
                        strncat(result[result_cnt], inner_row[output_field[k]-outer_field_cnt], MAX_FIELD_LENGTH);
                        strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                    }
                }
                result_cnt++;
            }
        }
    }
    printf("Result cnt:%d\n",result_cnt);
    return result_cnt;
}

// int execute_join_with_midres(int outer_cnt, char (*midres)[MAX_RECORD_LENGTH], const char* inner_query, 
//                              const char* join_col, char (*result)[MAX_RECORD_LENGTH])
int execute_join_with_midres(int outer_cnt, char **midres, const char* inner_query, const char* join_col1, 
                                const char* join_col2, int outputNum, char (*output)[MAX_FIELD_LENGTH], char **result)                             
{
    int inner_cnt=0;
    char inner_fields_record[MAX_RECORD_LENGTH];
    ocall_inner_loop(inner_query, &inner_cnt, inner_fields_record, MAX_RECORD_LENGTH);
    char* outer_fields_record = midres[0];
    // printf("%s\n", outer_fields_record);

    char outer_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    char inner_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  

    int outer_field_cnt = parse_record(outer_fields_record, outer_fields);
    int inner_field_cnt = parse_record(inner_fields_record, inner_fields);

    int* output_field = (int *)malloc(outputNum * sizeof(int));
    int field_cnt = 0;

    for(int i=0; i<outputNum; i++) {
        for(int j=0; j<outer_field_cnt; j++) {
            if(!strcmp(output[i], outer_fields[j])){
                strncat(result[0], outer_fields[j], MAX_FIELD_LENGTH);
                strncat(result[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = j;
                field_cnt ++;
            }
        }
        for(int j=0; j<inner_field_cnt; j++) {
            if(!strcmp(output[i], inner_fields[j])){
                strncat(result[0], inner_fields[j], MAX_FIELD_LENGTH);
                strncat(result[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = outer_field_cnt+j;
                field_cnt ++;
            }
        }
    }
    printf("join_col1:%s\n", join_col1);
    printf("join_col2:%s\n", join_col2);

    int outer_id=0, inner_id=0;
    for(int i=0; i<outer_field_cnt; i++) {
        // strncat(result[0], outer_fields[i], MAX_FIELD_LENGTH);
        // strncat(result[0], "|", MAX_FIELD_LENGTH);
        printf("outer fields:\n");
        printf("%s, %s\n", join_col1, outer_fields[i]);
        printf("%d\n", strcmp(join_col1, outer_fields[i]));
        if(!strcmp(join_col1, outer_fields[i])) {
            outer_id = i;
        }
    }
    for(int i=0; i<inner_field_cnt; i++) {
        if(!strcmp(join_col2, inner_fields[i])) {
            inner_id = i;
        } 
    }
    for(int i=0; i<outputNum; i++) {
        printf("%d, %s\n", output_field[i], output[i]);
    }

    printf("inner id:%d\n", inner_id);
    printf("outer id:%d\n", outer_id);

    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH];

    int result_cnt = 1;

    const char delimiter[] = "|";
    printf("inner count2:%d\n", inner_cnt);
    printf("outer count2:%d\n", outer_cnt);
    for(int i=1; i<outer_cnt; i++){
        strlcpy(outer_record, midres[i], MAX_RECORD_LENGTH);
        
        // printf("out record:%d\n",i);

        // 创建一个足够大的数组来存储分割后的子字符串
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int outer_index = 0;
        outer_index = parse_record(outer_record, outer_row);

        for(int j=0; j<inner_cnt; j++){     
            enclave_get_inner_record(j, inner_record, MAX_RECORD_LENGTH);
            
            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  // 假设每个子字符串不超过 100 个字符，最多分割 100 次
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            if(strncmp(outer_row[outer_id], inner_row[inner_id], MAX_FIELD_LENGTH) == 0){
                for(int k=0; k<outputNum; k++) {
                    if(output_field[k]<outer_field_cnt) {
                        strncat(result[result_cnt], outer_row[output_field[k]], MAX_FIELD_LENGTH);
                        strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                    } else {
                        strncat(result[result_cnt], inner_row[output_field[k]-outer_field_cnt], MAX_FIELD_LENGTH);
                        strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                    }
                }
                // for(int k=0; k<outer_index; k++){
                //     strncat(result[result_cnt], outer_row[k], MAX_FIELD_LENGTH);
                //     strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                // }
                // for(int k=0; k<inner_index; k++){
                //     if(k != inner_id) {
                //         strncat(result[result_cnt], inner_row[k], MAX_FIELD_LENGTH);
                //         strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                //     }
                // }
                result_cnt++;
            }
        }
    }
    return result_cnt;
}

// 这个函数还是最初版的，因为暂时用不到，用的时候需要修改到和上面两个函数同步
int execute_join_with_midres2(int outer_cnt, char (*midres1)[MAX_RECORD_LENGTH], int outer_id,
                              int inner_cnt, char (*midres2)[MAX_RECORD_LENGTH], int inner_id,
                              char (*result)[MAX_RECORD_LENGTH])
{
    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH];

    int result_cnt = 1;

    const char delimiter[] = "|";
    for(int i=1; i<outer_cnt; i++){
        strlcpy(outer_record, midres1[i], MAX_RECORD_LENGTH);
        
        // 创建一个足够大的数组来存储分割后的子字符串
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int outer_index = 0;
        outer_index = parse_record(outer_record, outer_row);

        for(int j=1; j<inner_cnt; j++){
            // enclave_get_inner_record(j, inner_record, MAX_RECORD_LENGTH);
            strlcpy(inner_record, midres2[i], MAX_RECORD_LENGTH);
            
            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  // 假设每个子字符串不超过 100 个字符，最多分割 100 次
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            if(strncmp(outer_row[outer_id], inner_row[inner_id], MAX_FIELD_LENGTH) == 0){
                for(int k=0; k<outer_index; k++){
                    strncat(result[result_cnt], outer_row[k], MAX_FIELD_LENGTH);
                    strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                }
                for(int k=0; k<inner_index; k++){
                    strncat(result[result_cnt], inner_row[k], MAX_FIELD_LENGTH);
                    strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                }
                result_cnt++;
            }
        }
    }
    return result_cnt;
}

void print_jsonnode(JsonNode* node) {
    if(node == NULL) {
        return;
    }
    print_jsonnode(node->left);

    printf("Jsonnode type:%s\n", node->nodeType);
    if(!strcmp(node->nodeType, "join")) {
        printf("filter:%s\n", node->joinFilter);
        for(int i=0; i<node->outputNum; i++) {
            printf("output[%d]:%s\n", i, node->output[i]);
        }
    } else if(!strcmp(node->nodeType, "scan")) {
        printf("relation name:%s\n", node->relName);
        printf("alias:%s\n", node->alias);
        for(int i=0; i<node->outputNum; i++) {
            printf("output[%d]:%s\n", i, node->output[i]);
        }
    }
    
    print_jsonnode(node->right);
}

void extract_join_col(const char *input, char *join_col1, char *join_col2) {
    const char *start1, *end1, *start2;
    
    start1 = strchr(input, '.');
    end1 = strchr(input, '=');
    
    if (start1 != NULL && end1 != NULL) {
        start1++;
        end1--;
        
        start2 = strchr(end1 + 1, '.');
        
        if (start2 != NULL) {
            size_t length1 = end1 - start1;
            size_t length2 = strlen(start2 + 1); 
            
            strncpy(join_col1, start1, length1);
            strncpy(join_col2, start2 + 1, length2); 
            join_col1[length1] = '\0';
            join_col2[length2] = '\0';
        }
    }
}

void malloc_array(char** result) 
{
    result = (char **)malloc(MAX_ROW_NUM * sizeof(char *));
    if (result == NULL) {
        printf("内存分配失败1\n");
        return;
    }
    for (int i = 0; i < MAX_ROW_NUM; i++) {
        result[i] = (char *)malloc(MAX_RECORD_LENGTH * sizeof(char));
        if (result[i] == NULL) {
            printf("内存分配失败2\n");
            return;
        }
    }
}

char** parse_jsonnode(JsonNode* node, int* row_num) {
    if(node == NULL) {
        return NULL;
    }

    char **left_res = parse_jsonnode(node->left, row_num);
    int left_num = *row_num;
    char **right_res = parse_jsonnode(node->right, row_num);
    int right_num = *row_num;


    if(!strcmp(node->nodeType, "scan")) {
        char sql[MAX_SQL_LENGTH] = "SELECT ";
        for(int i=0; i<node->outputNum; i++) {
            strncat(sql, node->output[i], MAX_SQL_LENGTH);
            if(i != node->outputNum-1) {
                strncat(sql, ", ", MAX_SQL_LENGTH);
            }
        }
        strncat(sql, " FROM ", MAX_SQL_LENGTH);
        strncat(sql, node->relName, MAX_SQL_LENGTH);
        strncat(sql, " ", MAX_SQL_LENGTH);
        strncat(sql, node->alias, MAX_SQL_LENGTH);
        if(node->joinFilter != NULL) {
            strncat(sql, " WHERE ", MAX_SQL_LENGTH);
            strncat(sql, node->joinFilter, MAX_SQL_LENGTH);
        }
        strlcpy(node->sqlStatement, sql, MAX_SQL_LENGTH);
        printf("%s\n", sql);
        return NULL;
    } else if (!strcmp(node->nodeType, "join")) {
        if(!strcmp(node->left->nodeType, "scan")) {
            if(!strcmp(node->right->nodeType, "scan")) {
                if(left_res!= NULL || right_res != NULL) {
                    printf("error!\n");
                }
                char sql1[MAX_SQL_LENGTH];
                char sql2[MAX_SQL_LENGTH];
                strlcpy(sql1, node->left->sqlStatement, MAX_SQL_LENGTH);
                strlcpy(sql2, node->right->sqlStatement, MAX_SQL_LENGTH);

                char filter[MAX_FILTER_LENGTH];
                char join_col1[MAX_FIELD_LENGTH];
                char join_col2[MAX_FIELD_LENGTH];
                strlcpy(filter, node->joinFilter, MAX_FILTER_LENGTH);
                extract_join_col(filter, join_col1, join_col2);

                
                // char output[node->outputNum][MAX_FIELD_LENGTH];
                // for(int i=0; i<node->outputNum; i++) {
                //     printf("%s\n", node->output[i]);
                // }
                // strlcpy(filter, node->joinFilter, MAX_FILTER_LENGTH);

                // malloc array  TODO: put in function
                char **mid_res = (char **)malloc(MAX_ROW_NUM * sizeof(char *));
                if (mid_res == NULL) {
                    printf("内存分配失败1\n");
                }
                for (int i = 0; i < MAX_ROW_NUM; i++) {
                    mid_res[i] = (char *)malloc(MAX_RECORD_LENGTH * sizeof(char));
                    if (mid_res[i] == NULL ) {
                        printf("内存分配失败2\n");
                    }
                }

                *row_num = execute_join(sql1, sql2, join_col1, join_col2, node->outputNum, node->output, mid_res);
                return mid_res;
            } else if(!strcmp(node->right->nodeType, "join")) {

            }
        } else if(!strcmp(node->left->nodeType, "join")) {
            if(!strcmp(node->right->nodeType, "scan")) {
                char sql[MAX_SQL_LENGTH];
                strlcpy(sql, node->right->sqlStatement, MAX_SQL_LENGTH);
                char filter[MAX_FILTER_LENGTH];
                char join_col1[MAX_FIELD_LENGTH];
                char join_col2[MAX_FIELD_LENGTH];
                strlcpy(filter, node->joinFilter, MAX_FILTER_LENGTH);
                extract_join_col(filter, join_col1, join_col2);
                // printf("%s\n", join_col1);
                // printf("%s\n", join_col2);

                char **mid_res = (char **)malloc(MAX_ROW_NUM * sizeof(char *));
                if (mid_res == NULL) {
                    printf("内存分配失败1\n");
                }
                for (int i = 0; i < MAX_ROW_NUM; i++) {
                    mid_res[i] = (char *)malloc(MAX_RECORD_LENGTH * sizeof(char));
                    if (mid_res[i] == NULL ) {
                        printf("内存分配失败2\n");
                    }
                }
                // char **mid_res;
                // malloc_array(mid_res);
                *row_num = execute_join_with_midres(left_num, left_res, sql, join_col1, join_col2, node->outputNum, node->output, mid_res);
                return mid_res;
            } else if(!strcmp(node->right->nodeType, "join")) {

            }
        }
    }


}

void enclave_generate_sql(JsonNode* node, size_t len) 
{
    JsonNode *current = node;
    // print_jsonnode(current);
    // malloc_array();

    int final_num = 0;
    char **final_res = parse_jsonnode(current, &final_num);

    printf("final result num is %d:\n", final_num-1);
    for(int i=0; i<final_num; i++){
        printf("%s\n", final_res[i]);
    }
    // free_array();

}

void enclave_process_row(const char* data) {
    printf("flag");
    printf("Enclave processed data: %s\n", data);
}